﻿using ErrorOr;
using Gym.Domain.Common;
using Gym.Domain.SubscriptionAggregate.Events;
using G = Gym.Domain.GymAggregate;

namespace Gym.Domain.SubscriptionAggregate
{
    public class Subscription: AggregateRoot
    {
        public SubscriptionType SubscriptionType { get; } = default!;
        private readonly List<Guid> _gymIds = new();
        private readonly int _maxGyms;
        private readonly Guid _adminId;

        public Subscription(
            SubscriptionType subscriptionType,
            Guid adminId,
            Guid? id = null) : base(id ?? Guid.NewGuid())
        {            
            SubscriptionType = subscriptionType;         
            _maxGyms = GetMaxGyms();
            _adminId = adminId;
        }

        public ErrorOr<Success> AddGym(G.Gym gym)
        {
            if (_gymIds.Contains(gym.Id))
            {
                return Error.Conflict("该健身房已经存在");
            }
            if (_gymIds.Count >= _maxGyms)
            {
                return SubscriptionErrors.CannotHaveMoreGymsThanSubscriptionAllows;
            }
            _gymIds.Add(gym.Id);

            _domainEvents.Add(new GymAddedEvent(this, gym));

            return Result.Success;
        }

        public int GetMaxGyms() => SubscriptionType.Name switch
        {
            nameof(SubscriptionType.Free) => 1,
            nameof(SubscriptionType.Starter) => 1,
            nameof(SubscriptionType.Pro) => 3,
            _ => throw new InvalidOperationException()
        };

        public int GetMaxRooms()
        {
            return SubscriptionType.Name switch
            {
                nameof(SubscriptionType.Free) => 1,
                nameof(SubscriptionType.Starter) => 3,
                nameof(SubscriptionType.Pro) => int.MaxValue,
                _ => throw new InvalidOperationException()
            };
        }

        public int GetMaxDailySessions() => SubscriptionType.Name switch
        {
            nameof(SubscriptionType.Free) => 4,
            nameof(SubscriptionType.Starter) => int.MaxValue,
            nameof(SubscriptionType.Pro) => int.MaxValue,
            _ => throw new InvalidOperationException()
        };

        public bool HasGym(Guid gymId)
        {
            return _gymIds.Contains(gymId);
        }

        private Subscription() { }
    }
}
